package com.garbagecode.util.pagination;

import java.util.List;

import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;

/**
 * 
 * @author cc.z
 *
 */
public class ResultBounds extends RowBounds {
	private String order;
	private Total total;

	public String getOrder() {
		return order;
	}

	public void setOrder(String order) {
		this.order = order;
	}

	public long getTotal() {
		if (total == null) {
			throw new RuntimeException("property 'total' is required");
		}
		
		return total.get();
	}

	public void setTotal(Total total) {
		this.total = total;
	}

	public ResultBounds() {

	}

	public ResultBounds(String order) {
		this.order = order;
	}

	public ResultBounds(RowBounds rowBounds) {
		super(rowBounds.getOffset(), rowBounds.getLimit());
	}

	public ResultBounds(int offset, int limit) {
		super(offset, limit);
	}

	public ResultBounds(RowBounds rowBounds, String order) {
		super(rowBounds.getOffset(), rowBounds.getLimit());
		this.order = order;
	}

	public ResultBounds(int offset, int limit, String order) {
		super(offset, limit);
		this.order = order;
	}

	public boolean hasBounds() {
		return (getOffset() != RowBounds.NO_ROW_OFFSET || getLimit() != RowBounds.NO_ROW_LIMIT
				|| (order != null && order.length() > 0));
	}

	public static ResultBounds wrap(RowBounds rowBounds) {
		ResultBounds resultBounds = null;

		if (rowBounds == null) {
			//
		} else if (rowBounds instanceof ResultBounds) {
			resultBounds = (ResultBounds) rowBounds;
		} else {
			resultBounds = new ResultBounds(rowBounds);
		}

		return resultBounds;
	}
	
	public static class Total extends RowBounds {
		private String statement;
		private Object parameter;
		private Long total;

		public Total(String statement, Object parameter) {
			this.statement = statement;
			this.parameter = parameter;
			this.total = null;
		}

		public long get() {
			if (total == null) {
				if (statement == null) {
					throw new RuntimeException("property 'statement' is required");
				}
				
				SqlSession sqlSession = ResultBoundsUtils.getSqlSession();
				List<Long> list = sqlSession.selectList(statement, parameter, this);
				
				if (list.size() >= 1) {
					total = list.get(0);
				} else {
					throw new RuntimeException("count rows for statement '" + statement + "' fail");
				}
			}
			
			return total;
		}
	}
}
